/*
 * Deptree.cpp
 *
 *  Created on: Dec 18, 2014
 *      Author: Phong
 */

#include "Deptree.h"
#include "Depstruct.h"
#include <iostream>
#include <string.h>
#include "Utils.h"
using namespace std;

Deptree::~Deptree() {
	freeTempArrays();

	for (int i = 0; i < nNodes; i++) {
		delete[] children[i][0];
		delete[] children[i][1];
		delete[] children[i];
		delete[] nChildren[i];
	}
	delete[] children;
	delete[] nChildren;
	delete[] word;
	delete[] pos;
	delete[] deprel;
	delete[] parent;
	delete[] dir;

	if (ds != NULL) Depstruct::free(ds);
}

Deptree::Deptree(int nWords) : SafeShare() {
	nNodes = nWords;
	word = new int[nNodes]();
	pos = new int[nNodes]();
	parent = new int[nNodes]();
	dir = new int[nNodes]();
	deprel = new int[nNodes]();
	ds = NULL;
	wordCands = NULL;

	nChildren = new int*[nNodes];
	children = new int**[nNodes];
	for (int i = 0; i < nNodes; i++) {
		nChildren[i] = new int[2]();
		children[i] = new int*[2];
		children[i][0] = new int[nNodes]();
		children[i][1] = new int[nNodes]();
	}

	gRep = NULL;
	pGRep = NULL;
	priorPGRep = NULL;
	gradPriorPGRep = NULL;
	EOCGRep = NULL;
	priorEOCGRep = NULL;
	gradPriorEOCGRep = NULL;
	gradGRep = NULL;
	gradpGRep = NULL;
	gradEOCGRep = NULL;

	gradheadRep = NULL;
	gradCRep = NULL;
	headRep = NULL;
	cRep = NULL;

	deprelProb = NULL;
	posProb = NULL;
	wordProb = NULL;
	EOCProb = NULL;
}

Deptree* Deptree::clone(bool cloneRep) {
	Deptree* tree = new Deptree(nNodes);
	memcpy(tree->word, word, sizeof(int)*nNodes);
	memcpy(tree->pos, pos, sizeof(int)*nNodes);
	memcpy(tree->parent, parent, sizeof(int)*nNodes);
	memcpy(tree->dir, dir, sizeof(int)*nNodes);
	memcpy(tree->deprel, deprel, sizeof(int)*nNodes);

	for (int i = 0; i < nNodes; i++) {
		memcpy(tree->nChildren[i], nChildren[i], sizeof(int)*2);
		memcpy(tree->children[i][0], children[i][0], sizeof(int)*nNodes);
		memcpy(tree->children[i][1], children[i][1], sizeof(int)*nNodes);
	}

	if (ds != NULL) tree->ds = (Depstruct*)ds->share();

	if (cloneRep) {
		if (gRep != NULL) {
			tree->gRep = new Matrix*[nNodes]();
			for (int i = 0; i < nNodes; i++)
				if (gRep[i] != NULL) tree->gRep[i] = gRep[i]->dup();
		}

		if (cRep != NULL) {
			tree->cRep = new Matrix*[nNodes]();
			for (int i = 0; i < nNodes; i++)
				if (cRep[i] != NULL) tree->cRep[i] = cRep[i]->dup();
		}

		if (headRep != NULL) {
			tree->headRep = new Matrix*[nNodes]();
			for (int i = 0; i < nNodes; i++)
				if (headRep[i] != NULL) tree->headRep[i] = headRep[i]->dup();
		}
	}
	return tree;
}

string Deptree::toString(Dictionary* vocaDic, Dictionary* posDic, Dictionary* deprelDic) {
	string str;
	for (int i = 1; i < nNodes; i++) {
		str	+= to_string(i) + "\t"
				+ vocaDic->id2word[word[i]] + "\t"
				+ posDic->id2word[pos[i]] + "\t"
				+ to_string(parent[i]) + "\t"
				+ to_string(dir[i]) + "\t"
				+ deprelDic->id2word[deprel[i]] + "\n";
	}

	return str;
}

void Deptree::getSentence(Dictionary* vocaDic, Dictionary* posDic, Dictionary* deprelDic, vector<string> &sentence) {
	int curid = -1;
	return getSentence(vocaDic, posDic, deprelDic, sentence, curid, -1, 0);
}

void Deptree::getSentence(Dictionary* vocaDic, Dictionary* posDic, Dictionary* deprelDic,
		vector<string> &sentence, int &curid, int headid, int node) {

	vector<string> leftChildren;
	for (int i = nChildren[node][0]-1; i >= 0; i--)
		getSentence(vocaDic, posDic, deprelDic, leftChildren, curid, -1, children[node][0][i]);

	curid++;

	for (string str : leftChildren) {
		Utils::stringReplace(str, "-1", to_string(curid));
		sentence.push_back(str);
	}

	if (node > 0)
		sentence.push_back(to_string(curid) + "\t" +
				vocaDic->id2word[word[node]] + "\t" +
				"_\t" +
				posDic->id2word[pos[node]] + "\t" +
				posDic->id2word[pos[node]] + "\t" +
				"_\t" +
				to_string(headid) + "\t" +
				deprelDic->id2word[deprel[node]] + "\t_\t_");

	int thisid = curid;

	for (int i = 0; i < nChildren[node][1]; i++)
		getSentence(vocaDic, posDic, deprelDic, sentence, curid, thisid, children[node][1][i]);
}

void Deptree::freeTempArrays(){
	Matrix::free(gRep, nNodes);
	Matrix::free(gradGRep, nNodes);

	Matrix::free(headRep, nNodes);
	Matrix::free(gradheadRep, nNodes);

	Matrix::free(cRep, nNodes);
	Matrix::free(gradCRep, nNodes);

	Matrix::free(pGRep, nNodes);
	Matrix::free(gradpGRep, nNodes);

	Matrix::free(priorPGRep, nNodes);
	Matrix::free(gradPriorPGRep, nNodes);

	Matrix::free(priorEOCGRep, 2, nNodes);
	Matrix::free(gradPriorEOCGRep, 2, nNodes);

	Matrix::free(EOCGRep, 2, nNodes);
	Matrix::free(gradEOCGRep, 2, nNodes);

	Matrix::free(deprelProb, nNodes);
	Matrix::free(posProb, nNodes);
	Matrix::free(wordProb, nNodes);
	Matrix::free(EOCProb, 2, nNodes);
}


